package cn.lili.modules.serviceimpl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.member.entity.dto.UserInfoDTO;
import cn.lili.modules.message.entity.dos.Message;
import cn.lili.modules.message.entity.enums.MessageSendClient;
import cn.lili.modules.message.entity.enums.RangeEnum;
import cn.lili.modules.operationcenter.entity.dos.OperationCenter;
import cn.lili.modules.operationcenter.entity.enums.OperationCenterStatusEnum;
import cn.lili.modules.operationcenter.entity.vos.OperationCenterSearchParams;
import cn.lili.modules.operationcenter.entity.vos.OperationCenterVo;
import cn.lili.modules.mapper.OperationCenterMapper;
import cn.lili.modules.service.OperationCenterService;
import cn.lili.modules.store.entity.enums.StoreStatusEnum;
import cn.lili.modules.system.client.IRegionClient;
import cn.lili.modules.system.client.SmsClient;
import cn.lili.modules.system.entity.dos.Region;
import cn.lili.modules.system.entity.params.SmsParams;
import cn.lili.modules.verification.entity.enums.VerificationEnums;
import cn.lili.mybatis.util.PageUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
@Slf4j
public class OperationCenterServiceImpl extends ServiceImpl<OperationCenterMapper, OperationCenter> implements OperationCenterService {

    private final Cache cache;

    private final UserClient userClient;
    private final SmsClient smsClient;

    private final IRegionClient regionClient;

    @Override
    public OperationCenter getOperationCenter(String userId) {
        OperationCenter operationCenter = (OperationCenter) cache.get(CachePrefix.OPERATION_CENTER.getPrefix() + userId);
        if (operationCenter == null) {
            LambdaQueryWrapper<OperationCenter> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OperationCenter::getUserId, userId);
            queryWrapper.last("limit 1");
            operationCenter = this.baseMapper.selectOne(queryWrapper);
            cache.put(CachePrefix.OPERATION_CENTER.getPrefix() + userId, operationCenter, 60L);
        }
        return operationCenter;

    }

    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public void edit(OperationCenter operationCenter) {
        if (operationCenter != null && StringUtils.isNotEmpty(operationCenter.getId())) {
            OperationCenter oc = this.getById(operationCenter.getId());
            LambdaQueryWrapper<OperationCenter> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OperationCenter::getOperationName, operationCenter.getOperationName());
            queryWrapper.ne(OperationCenter::getId, operationCenter.getId());
            queryWrapper.last("limit 1");
            OperationCenter ocName = this.getOne(queryWrapper);
            if (null != ocName) {
                throw new ServiceException("运营中心名称已存在");
            }

            if (StringUtils.isNotEmpty(operationCenter.getProvinceId())) {
                queryWrapper.clear();
                queryWrapper.eq(OperationCenter::getProvinceId, operationCenter.getProvinceId());
                queryWrapper.ne(OperationCenter::getId, operationCenter.getId());
                queryWrapper.last("limit 1");
                OperationCenter ocProvinceId = this.getOne(queryWrapper);
                if (null != ocProvinceId) {
                    throw new ServiceException("所选省份已存在");
                }
            }

            if (oc != null) {
                BeanUtil.copyProperties(operationCenter, oc);
                oc.setId(operationCenter.getId());
                if (StoreStatusEnum.REFUSED.name().equals(oc.getStatus())) {
                    oc.setStatus(StoreStatusEnum.APPLYING.name());
                }
                this.updateById(oc);
            }
            cache.remove(CachePrefix.OPERATION_CENTER.getPrefix() + operationCenter.getId());
        } else {
            throw new ServiceException(ResultCode.OPERATION_CENTER_NOT_EXIST);
        }
    }

    @Override
    public void add(OperationCenter operationCenter) {
        if (!SceneEnums.MANAGER.equals(Objects.requireNonNull(UserContext.getCurrentUser()).getScene())) {
            throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR);
        }

        LambdaQueryWrapper<OperationCenter> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OperationCenter::getOperationName, operationCenter.getOperationName());
        List<OperationCenter> list = this.list(queryWrapper);
        if (ObjectUtil.isNotNull(list) && !list.isEmpty()) {
            throw new ServiceException(ResultCode.OPERATION_CENTER_EXIST_ERROR);
        }

        queryWrapper.clear();
        queryWrapper.eq(OperationCenter::getProvinceId, operationCenter.getProvinceId());
        List<OperationCenter> list2 = this.list(queryWrapper);
        if (ObjectUtil.isNotNull(list2) && !list2.isEmpty()) {
            throw new ServiceException("您所选的运营中心省份已被使用");
        }

        User user1 = userClient.getByUserName(operationCenter.getUserName(), SceneEnums.OPERATION_CENTER.name());
        if (null != user1) {
            throw new ServiceException("用户名已存在");
        }
        operationCenter.setId(SnowFlake.getIdStr());
        operationCenter.setStatus(StoreStatusEnum.APPLYING.name());
        User user = userClient.register(UserInfoDTO.builder()
                .username(operationCenter.getUserName())
                .password(new BCryptPasswordEncoder().encode(operationCenter.getPassword()))
                .mobile(operationCenter.getOperationPhone())
                .extendName(operationCenter.getOperationName())
                .nickName(operationCenter.getOperationName())
                .scene(SceneEnums.valueOf(operationCenter.getScene()))
                .extendId(operationCenter.getId())
                .isSuper(true)
                .shopkeeper(true)
                .build());

        operationCenter.setUserId(user.getId());
        this.save(operationCenter);
    }

    @Override
    public Page<OperationCenterVo> findByConditionPage(OperationCenterSearchParams operationCenterSearchParams, PageVO page) {
        QueryWrapper<OperationCenterVo> queryWrapper = operationCenterSearchParams.queryWrapper();
        return this.baseMapper.findByConditionPage(PageUtil.initPage(page), queryWrapper);
    }

    @Override
    public OperationCenter getOperationCenterById(String id) {
        OperationCenter operationCenter = (OperationCenter) cache.get(CachePrefix.OPERATION_CENTER.getPrefix() + id);
        if (operationCenter == null) {
            operationCenter = getById(id);
            cache.put(CachePrefix.OPERATION_CENTER.getPrefix() + id, operationCenter, 7200L);
        }
        return operationCenter;
    }

    @Override
    public OperationCenter getByAddressId(String provinceId) {
        LambdaQueryWrapper<OperationCenter> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OperationCenter::getProvinceId, provinceId);
        queryWrapper.last("limit 1");
        return this.baseMapper.selectOne(queryWrapper);
    }

    @Override
    public void disable(String id) {
        OperationCenter operationCenter = this.getById(id);
        if (operationCenter != null) {
            operationCenter.setStatus(StoreStatusEnum.CLOSED.value());
            this.updateById(operationCenter);
            cache.remove(CachePrefix.OPERATION_CENTER.getPrefix() + id);
            Message message = new Message();
            message.setMessageRange(RangeEnum.APPOINT.name());
            message.setMessageClient(MessageSendClient.STORE.name());
            return;
        }
        throw new ServiceException(ResultCode.OPERATION_CENTER_NOT_EXIST);
    }

    @Override
    public void enable(String id, String status) {
        OperationCenter operationCenter = this.getById(id);
        if (operationCenter != null) {
            if (CharSequenceUtil.isNotEmpty(status)) {
                operationCenter.setStatus(status);
            }else {
                operationCenter.setStatus(StoreStatusEnum.OPEN.value());
            }

            this.updateById(operationCenter);
            cache.remove(CachePrefix.OPERATION_CENTER.getPrefix() + id);
            return;
        }
        throw new ServiceException(ResultCode.OPERATION_CENTER_NOT_EXIST);
    }

    @Override
    public void delete(String id) {
        OperationCenter operationCenter = this.getById(id);
        if (operationCenter != null) {
            this.removeById(id);
            //删除用户账户
            this.userClient.deleteUserByExtId(id);
            return;
        }
        throw new ServiceException(ResultCode.OPERATION_CENTER_NOT_EXIST);
    }

    @Override
    public OperationCenter getById(String id) {
        return this.baseMapper.selectById(id);
    }

    @Override
    public List<OperationCenter> select(String name) {
        LambdaQueryWrapper<OperationCenter> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(name)) {
            lambdaQueryWrapper.like(OperationCenter::getProvinceName, name);
        }
        lambdaQueryWrapper.select(OperationCenter::getUserId, OperationCenter::getProvinceName);
        return super.list(lambdaQueryWrapper);
    }

    /**
     * 设置运营中心提现银行账户
     * @param operationCenter
     * @return
     */
    @Override
    public ResultMessage<OperationCenter> setBankAccountByOperationId(OperationCenter operationCenter, String uuid) {
        this.checkSetBankAccountOperation(operationCenter);
        AuthUser authUser = UserContext.getCurrentUser();
        OperationCenter operationCenterData = this.getOperationCenter(authUser.getId());
        if (null == operationCenterData) {
            throw new ServiceException("数据错误");
        }
        //短信验证
        SmsParams params = new SmsParams();
        params.setVerificationEnums(VerificationEnums.OPERATION_SET_BANK_ACCOUNT);
        params.setMobile(operationCenterData.getOperationPhone());
        params.setUuid(uuid);
        params.setCode(operationCenter.getSmsCode());
//        boolean flag = smsClient.verifyCode(params);
//        if (!flag) {
//            throw new ServiceException("验证码错误");
//        }
        operationCenterData.setSettlementBankAccountName(operationCenter.getSettlementBankAccountName());
        operationCenterData.setSettlementBankAccountNumber(operationCenter.getSettlementBankAccountNumber());
        operationCenterData.setSettlementBankName(operationCenter.getSettlementBankName());
        operationCenterData.setSettlementBankAddress(operationCenter.getSettlementBankAddress());
        int result = baseMapper.updateById(operationCenterData);
        cache.remove(CachePrefix.OPERATION_CENTER.getPrefix() + operationCenterData.getUserId());
        return result > 0 ? ResultUtil.success() : ResultUtil.error(400, "更新失败");
    }


    /**
     * 检查设置运营中心提现银行卡参数
     * @param operationCenter
     */
    private void checkSetBankAccountOperation(OperationCenter operationCenter) {
//        if (StrUtil.isEmpty(operationCenter.getSmsCode())) {
//            throw new ServiceException("短信验证码不可为空");
//        }
        if (StrUtil.isEmpty(operationCenter.getSettlementBankAccountName())) {
            throw new ServiceException("银行名称不可为空");
        }
        if (StrUtil.isEmpty(operationCenter.getSettlementBankAccountNumber())) {
            throw new ServiceException("银行卡号不可为空");
        }
        if (StrUtil.isEmpty(operationCenter.getSettlementBankName())) {
            throw new ServiceException("银行名称不可为空");
        }
//        if (StrUtil.isEmpty(operationCenter.getSettlementBankAddress())) {
//            throw new ServiceException("开户行所在地不可为空");
//        }
    }


    /**
     * 发送验证码
     * @return
     */
    @Override
    public ResultMessage<Object> sendSMSVerificationCode(String uuid) {
        log.info("#sendSMSVerificationCode# 进入运营中心发送短信验证码,uuid:{}", uuid);
        String userId = UserContext.getCurrentUser().getId();
        log.info("#sendSMSVerificationCode# 运营中心发送短信验证码,userid:{}", userId);
        SmsParams smsParams = new SmsParams();
        smsParams.setVerificationEnums(VerificationEnums.OPERATION_SET_BANK_ACCOUNT);
        OperationCenter operationCenter = this.getOperationCenter(userId);
        if (null == operationCenter || StrUtil.isEmpty(operationCenter.getOperationPhone())) {
            throw new ServiceException("未找到运营中心手机号信息");
        }
        log.info("#sendSMSVerificationCode# 运营中心发送短信验证码,operationCenter:{}", JSONObject.toJSONString(operationCenter));
        smsParams.setMobile(operationCenter.getOperationPhone());
        smsParams.setUuid(uuid);
        smsClient.sendSmsCode(smsParams);
        return ResultUtil.success();
    }


    /**
     * 根据proviceId list批量获取OperationCenter集合
     * @param provinceIdList
     * @return
     */
    @Override
    public List<OperationCenter> getOperationCenterListByProviceIds(List<String> provinceIdList) {
        LambdaQueryWrapper<OperationCenter> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(OperationCenter::getId, OperationCenter::getOperationName, OperationCenter::getProvinceId);
        lambdaQueryWrapper.in(OperationCenter::getProvinceId, provinceIdList);
        lambdaQueryWrapper.eq(OperationCenter::getStatus, OperationCenterStatusEnum.OPEN.name());
        return baseMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 获取省下面的市
     * @return
     */
    @Override
    public List<Region> getRegionByParentId() {
        OperationCenter operationCenter = this.getOperationCenter(Objects.requireNonNull(UserContext.getCurrentUser()).getId());
        return regionClient.getRegionByParentId(operationCenter.getProvinceId());
    }
}
